#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <windows.h>

#include <string>
#include <vector>
#include <algorithm>

// Interface libraries IUP and OpenGL: --------------------------//
#include <gl/Glut.h>

#include <iup.h>
#include <iupgl.h>
#include <iupcontrols.h>


// Computer vision libraries: -----------------------------------//
#include <cv.h>

// Utilities library: -------------------------------------------//



#include "CameraDriveImagSeq.h"
#include "viewer.h"
#include "scene.h"
#include "processing.h"

int update_image_UI();


#define PI_ 3.14159265358979323846

#ifndef ABS
#define ABS(a) (((a)<0)?-(a):(a))
#endif

using namespace std;


//--------------------------------------------------------------//
//	Principal Objects											//
//--------------------------------------------------------------//
string mCanvasSize;
int mWCanvas , mHCanvas ; 
bool isTurnOnImageCapture = false,
isTurnOnShowImage = true;
bool isPlayTrack = false;

Scene g_scene;
Processing *g_processing = NULL;

int mouse_click_event_cb(Ihandle* ih,int but,int pressed,int x,int y,char* status);



class Iup
{
public:
	//- Canvas : ----------------------------------------------------//
	Ihandle *_canvas;		// handle to unique canvas 

	
	Ihandle *dialog, *statusbar, *box , *toolbar,*label;
	Ihandle *loadSequenceButton, *saveButton;
	
	Ihandle *imageStartButton, *imageStopButton, 
		*imagePreviousButton,*imageNextButton,*imageFrameSeek,	 *imageFrameText
		;
	
};





#define INTIUP(x) _iup.x

Iup _iup;




//---------------------------------------------------------------//
//	Pointer 2D coordinates of markers 
//---------------------------------------------------------------//

char * get_file_name_cb( char rw, char* filter )
{
	Ihandle* getfile = IupFileDlg();
	char* filename = NULL;

	IupSetAttribute(getfile, IUP_TITLE, "File selection"  );

	if (rw == 'r') 
	{
		IupSetAttribute(getfile, IUP_DIALOGTYPE, IUP_OPEN);
		IupSetAttribute(getfile, IUP_TITLE, "Open File");
	} 
	else 
	{
		IupSetAttribute(getfile, IUP_DIALOGTYPE, IUP_SAVE);
		IupSetAttribute(getfile, IUP_TITLE, "Save File");
	};

	IupSetAttribute(getfile, IUP_FILTER, filter);
	IupSetAttribute(getfile, IUP_FILTERINFO, filter);
	// Put pop up dialog in the center of the windows  
	IupPopup(getfile, IUP_CENTER, IUP_CENTER);  

	filename = IupGetAttribute(getfile, IUP_VALUE);
	return filename;
}


bool image_sequence_load()
{	
	const char* filename = NULL;
	filename = get_file_name_cb('r', "*.sqd" );

	if (!filename)
	{
		return false;
	}

	if (!g_scene.load(filename) || !update_image_UI() ) 
	{
		printf("\nCan't read configuration file.\n");
		return false;
	}
	if (!g_scene._imageCurrentRaw)
	{
		return false;	
	}
	if (g_processing)
	{
		delete g_processing;
	}
	g_processing = Processing::create(g_scene._imageDataSource->getWidth(),g_scene._imageDataSource->getHeight());

	return true;	
	
}



//----------------------------------------------------------------------//
// app_read_image_sequence
// - Read image file.
//----------------------------------------------------------------------//
int read_image_sequence(int index)
{	
	if (g_scene._imageDataSource==NULL)
	{
		return 0;
	}
	g_scene._imageDataSource->setPositionIndex(index);
	return update_image_UI();	
}

int update_image_UI()
{	
	if (g_scene._imageDataSource==NULL)
	{
		return 0;
	}

	if(!g_scene.updateCurrentImage())
	{
		g_scene._imageDataSource->stepR();
		g_scene.updateCurrentImage();
		isPlayTrack = false;
	}

	
	IupSetfAttribute(INTIUP(imageFrameText),IUP_VALUE,"%d",g_scene._imageDataSource->getPositionIndex());
	IupSetfAttribute(INTIUP(imageFrameSeek),IUP_VALUE,"%lf",g_scene._imageDataSource->getPositionIndexbyPercent());

	return 1;
}



// ------------------------------------------// 
// app_image_start_cb
// - Start show image sequence.
// ------------------------------------------// 
int image_start_cb()
{
	isPlayTrack = true;	
	return IUP_DEFAULT;
}

// ------------------------------------------// 
// app_image_stop_cb
// - Stop show image sequence.
// ------------------------------------------//
int image_stop_cb()
{
	isPlayTrack = false;
	return IUP_DEFAULT;
}
int image_seek_cb(Ihandle *ih, double val)
{
	if (g_scene._imageDataSource==NULL)
	{
		return 0;
	}
	isPlayTrack = false;
	g_scene._imageDataSource->setPositionIndexbyPercent(val);
	return update_image_UI();
	return IUP_DEFAULT;
}



//--------------------------------------------------------//
// change_current_frame_cb
// - Update image to current frame 
//--------------------------------------------------------//
int change_current_frame_cb(Ihandle *self, int c, char *after)
{
	if(c == 13)
	{  // Enter key = 13 
		int mTempFrame;
		mTempFrame = IupGetInt(INTIUP(imageFrameText),IUP_VALUE);			
		read_image_sequence(mTempFrame);
		

	};
	return IUP_DEFAULT;
}





//-----------------------------------------------------------------------------//
// app_next_image_cb
// - Go to next frame 
//-----------------------------------------------------------------------------//
void next_image_cb()
{
	if (g_scene._imageDataSource==NULL)
	{
		return;
	}
	g_scene._imageDataSource->stepF();	
	update_image_UI();
	
}

//-----------------------------------------------------------------------------//
// app_previous_image_cb
// - Go to previous frame 
//-----------------------------------------------------------------------------//
void previous_image_cb()
{
	if (g_scene._imageDataSource==NULL)
	{
		return;
	}
	g_scene._imageDataSource->stepR();	
	update_image_UI();
}

//-----------------------------------------------------------------------------//
// app_get_XY_init_pattern_location_cb
// - Get 2D coordinate in canvas where the mouse select
//-----------------------------------------------------------------------------//
int mouse_move_event_cb(Ihandle *ih, int x, int y, char *status)
{
	//printf("%d %d %d\n",_global._idSelect,x,(mHCanvas -y));

	return IUP_DEFAULT;
}

int mouse_click_event_cb(Ihandle* ih,int but,int pressed,int x,int y,char* status)
{
	int mIndex = 0,  mCurrentInitBoundaringPtsCounter = 0;

	if(but == IUP_BUTTON1 && pressed)
	{		
	}
	if(but == IUP_BUTTON1 && !pressed)
	{	
	}
	if (but == IUP_BUTTON3 && pressed)
	{		
		next_image_cb();		
	}

	return IUP_DEFAULT;
};

//----------------------------//
// save_cb
// - Load save file dialog 
//----------------------------//  
int save_cb(Ihandle *self)
{
	get_file_name_cb('w',"*.*");
	return IUP_DEFAULT;
}

//----------------------------//
// load_cb
// - Load read file dialog 
//----------------------------//  
int load_sequence_cb(void)
{
	
	if (!image_sequence_load())
	{
		IupSetAttribute(INTIUP(imageStartButton),IUP_ACTIVE,IUP_OFF);
		IupSetAttribute(INTIUP(imageStopButton),IUP_ACTIVE,IUP_OFF);
		IupSetAttribute(INTIUP(imagePreviousButton),IUP_ACTIVE,IUP_OFF);
		IupSetAttribute(INTIUP(imageNextButton),IUP_ACTIVE,IUP_OFF);
		IupSetAttribute(INTIUP(imageFrameSeek),IUP_ACTIVE,IUP_OFF);
		isTurnOnImageCapture = false;
		return IUP_DEFAULT;
	}

	update_image_UI();
	IupSetAttribute(INTIUP(imageStartButton),IUP_ACTIVE,IUP_ON);
	IupSetAttribute(INTIUP(imageStopButton),IUP_ACTIVE,IUP_ON);
	IupSetAttribute(INTIUP(imagePreviousButton),IUP_ACTIVE,IUP_ON);
	IupSetAttribute(INTIUP(imageNextButton),IUP_ACTIVE,IUP_ON);
	IupSetAttribute(INTIUP(imageFrameSeek),IUP_ACTIVE,IUP_ON);
	
	
	isTurnOnImageCapture = true;
	return IUP_DEFAULT;
}

//////////////////////////////////////////////////////////////////////////

//---------------------------------------------------------------------//
// idle_cb
// - Idle routine.
//---------------------------------------------------------------------//
int idle_cb(void)
{
	if(isTurnOnImageCapture)
	{
		// Draw final scene in canvas
		g_processing->process(g_scene._imageCurrentRaw);
		app_draw_video_image_cb(INTIUP(_canvas),g_scene) ;		
		app_draw_teapot_cb(INTIUP(_canvas),g_processing);
		app_draw_refresh_cb(INTIUP(_canvas)); 
	};

	if(isPlayTrack)
	{
		if (g_scene._imageDataSource==NULL)
		{
			return IUP_DEFAULT;
		}
		g_scene._imageDataSource->stepF();
		update_image_UI();
	}

	return IUP_DEFAULT;
}

//-------------------------------------------------------------------//
// exit_cb
// - End routines.                                                   
//-------------------------------------------------------------------//
int exit_cb()
{
	return IUP_CLOSE;
}

//---------------------------------------------------------------------------//
// init
// - Init program definitions.                                               
//---------------------------------------------------------------------------//




Ihandle* initInputImageSequenceFrame( void )
{

	INTIUP(loadSequenceButton) = IupButton("load sequence", IUP_ACTION);
	IupSetAttribute(INTIUP(loadSequenceButton),"TIP","load sequence");
	IupSetAttribute(INTIUP(loadSequenceButton),IUP_IMAGE,"IUP_IMGBUT_OPEN");
	IupSetCallback(INTIUP(loadSequenceButton), IUP_ACTION, (Icallback)load_sequence_cb);

	INTIUP(saveButton) = IupButton("save", IUP_ACTION);
	IupSetAttribute(INTIUP(saveButton),"TIP","Salva Alguma coisa");
	IupSetAttribute(INTIUP(saveButton),IUP_IMAGE,"IUP_IMGBUT_SAVE");
	IupSetCallback(INTIUP(saveButton), IUP_ACTION, (Icallback)save_cb);
	
	INTIUP(imageFrameText) = IupText(IUP_ACTION);
	IupSetAttribute( INTIUP(imageFrameText), IUP_SIZE,     "20x");
	IupSetAttribute( INTIUP(imageFrameText), IUP_K_ANY,    "k_any");
	IupSetfAttribute(INTIUP(imageFrameText), IUP_VALUE,    "?");
	IupSetAttribute( INTIUP(imageFrameText), IUP_ALIGNMENT,"ARIGHT");
	IupSetCallback(  INTIUP(imageFrameText),  IUP_ACTION,   (Icallback)change_current_frame_cb);


	Ihandle* sequenceFrame = IupHbox(INTIUP(loadSequenceButton),INTIUP(saveButton),INTIUP(imageFrameText),IupFill(),NULL);
	
	return sequenceFrame;

}

Ihandle* initInputImageControlsFrame( void )
{

	// creates the toolbar and its buttons 

	INTIUP(imageStartButton) = IupButton("imageStartButton", IUP_ACTION);
	IupSetAttribute(INTIUP(imageStartButton),"TIP","Start capture image sequence");
	IupSetAttribute(INTIUP(imageStartButton),IUP_IMAGE,"IUP_IMGBUT_PLAY");
	IupSetAttribute(INTIUP(imageStartButton),IUP_ACTIVE,IUP_OFF);
	IupSetAttribute(INTIUP(imageStartButton),IUP_EXPAND,IUP_NO);

	INTIUP(imageStopButton) = IupButton("imageStopButton", IUP_ACTION);
	IupSetAttribute(INTIUP(imageStopButton),"TIP","Stop capture image sequence");
	IupSetAttribute(INTIUP(imageStopButton),IUP_IMAGE,"IUP_IMGBUT_STOP");
	IupSetAttribute(INTIUP(imageStopButton),IUP_ACTIVE,IUP_OFF);
	IupSetAttribute(INTIUP(imageStopButton),IUP_EXPAND,IUP_NO);

	INTIUP(imageNextButton) = IupButton("imageNextButton", IUP_ACTION);
	IupSetAttribute(INTIUP(imageNextButton),"TIP","Next image sequence");
	IupSetAttribute(INTIUP(imageNextButton),IUP_IMAGE,"IUP_IMGBUT_FOWARD");
	IupSetAttribute(INTIUP(imageNextButton),IUP_ACTIVE,IUP_OFF);
	IupSetAttribute(INTIUP(imageNextButton),IUP_EXPAND,IUP_NO);

	INTIUP(imagePreviousButton) = IupButton("imagePreviousButton", IUP_ACTION);
	IupSetAttribute(INTIUP(imagePreviousButton),"TIP","Previous image sequence");
	IupSetAttribute(INTIUP(imagePreviousButton),IUP_IMAGE,"IUP_IMGBUT_REWIND");
	IupSetAttribute(INTIUP(imagePreviousButton),IUP_ACTIVE,IUP_OFF);
	IupSetAttribute(INTIUP(imagePreviousButton),IUP_EXPAND,IUP_NO);

	INTIUP(imageFrameSeek) = IupVal(IUP_ACTION);
	IupSetAttribute(INTIUP(imageFrameSeek),"TIP","Previous image sequence");
	IupSetAttribute(INTIUP(imageFrameSeek),IUP_IMAGE,"IUP_IMGBUT_REWIND");
	IupSetAttribute(INTIUP(imageFrameSeek),IUP_ACTIVE,IUP_OFF);
	IupSetAttribute(INTIUP(imageFrameSeek),IUP_EXPAND,IUP_YES);


	IupSetCallback(INTIUP(imageStartButton),IUP_ACTION,(Icallback)image_start_cb);
	IupSetCallback(INTIUP(imageStopButton), IUP_ACTION,(Icallback)image_stop_cb);	
	IupSetCallback(INTIUP(imageNextButton), IUP_ACTION,(Icallback)next_image_cb);
	IupSetCallback(INTIUP(imagePreviousButton), IUP_ACTION,(Icallback)previous_image_cb);
	IupSetCallback(INTIUP(imageFrameSeek),IUP_MOUSEMOVE_CB,(Icallback)image_seek_cb);


	Ihandle* inputImageControlFrame = 
		IupVbox(IupHbox(initInputImageSequenceFrame(),IupSetAttributes(IupFill(),"SIZE = 5"),NULL),
		
		IupHbox(INTIUP(imageStartButton)
		,INTIUP(imageStopButton)
		,IupSetAttributes(IupFill(),"SIZE = 3")
		,INTIUP(imagePreviousButton)
		,INTIUP(imageNextButton)
		,IupSetAttributes(IupFill(),"SIZE = 10")
		,INTIUP(imageFrameSeek)
		,NULL),NULL
		);	

	return inputImageControlFrame;

}

void initIupCanvas( Ihandle* glCanvas,int w,int h )
{	
	string cmWCanvas, cmHCanvas;
	_itoa_s((w+1),(char*)cmWCanvas.c_str(),5,10);
	_itoa_s((h+1),(char*)cmHCanvas.c_str(),5,10);
	mCanvasSize = cmWCanvas.c_str();
	mCanvasSize +="x";	
	mCanvasSize += cmHCanvas.c_str();

	
	IupSetAttribute( glCanvas, IUP_BUFFER, IUP_DOUBLE);
	IupSetAttribute( glCanvas, IUP_RASTERSIZE, (char*)mCanvasSize.c_str() );
	IupSetAttribute( glCanvas, IUP_COLOR, IUP_RGBA);
	
	IupSetCallback(glCanvas, IUP_BUTTON_CB,(Icallback)mouse_click_event_cb);
	IupSetCallback(glCanvas, IUP_MOTION_CB,(Icallback)mouse_move_event_cb);
		
}

int init(void)
{
	mWCanvas = 320;
	mHCanvas = 240;
	
	Ihandle *controlsFrame;

	// create frame to capture video image of connected devices 
	controlsFrame = IupFrame(
		IupVbox(initInputImageControlsFrame(),NULL)
		);
	IupSetAttributes(controlsFrame, "FGCOLOR=\"0 0 0\", TITLE=\"Controls:\"");	
	IupSetAttribute(controlsFrame, "EXPAND", "HORIZONTAL");

	// join all widgets in one widget 
	INTIUP(toolbar)= IupVbox(		
		IupHbox(controlsFrame,NULL),
		NULL);

	IupSetAttribute(INTIUP(toolbar),IUP_MARGIN,"2x2");
	IupSetAttribute(INTIUP(toolbar),IUP_ALIGNMENT,"ALEFT");

	INTIUP(_canvas) = IupGLCanvas("");
	initIupCanvas(INTIUP(_canvas),mWCanvas,mHCanvas);
	IupSetAttribute(INTIUP(_canvas), IUP_EXPAND, IUP_NO);

	// Link callback names with function defined
	IupSetFunction(IUP_IDLE_ACTION, (Icallback)idle_cb);
	IupSetFunction("exit_cb", (Icallback)exit_cb);


	// the status bar is just a label to put some useful information in run time 
	INTIUP(label) = IupLabel("status");
	IupSetAttribute(INTIUP(label), "EXPAND", "HORIZONTAL");
	IupSetAttribute(INTIUP(label), "FONT", "COURIER_NORMAL_10");
	INTIUP(statusbar) = IupSetAttributes(IupHbox(
		IupFrame(IupHbox(INTIUP(label), NULL)), 
		NULL), "MARGIN=5x5");

	// This is the most external box that puts together
	// the toolbar, the four canvas and the status bar 
	INTIUP(box) = 	IupVbox(
		INTIUP(toolbar),
		IupHbox(INTIUP(_canvas),IupFill(),NULL),
		IupFill(),
		INTIUP(statusbar), 
		NULL);

	// Create the dialog and set its attributes 
	INTIUP(dialog) = IupDialog(INTIUP(box));
	
	IupSetAttribute(INTIUP(dialog), IUP_TITLE,"RA 2010");
	IupSetAttribute(INTIUP(dialog), IUP_ICON, "IUP_IMGLBL_TECGRAF");
	IupSetAttribute(INTIUP(dialog), IUP_CLOSE_CB, "app_exit_cb");
	IupShowXY(INTIUP(dialog), IUP_CENTER, IUP_CENTER);

	return IUP_DEFAULT;
}

//-------------------------------------------------------------------------//
// Main function														   //
//-------------------------------------------------------------------------//

int main(void) 
{
	IupOpen(0,NULL);
	IupControlsOpen(); 
	IupImageLibOpen();
	IupGLCanvasOpen();

	if ( init() )
	{
		init_video_canvas(INTIUP(_canvas), mWCanvas,mHCanvas);
		IupMainLoop(); 
		IupDestroy(INTIUP(dialog));
	}
	else
	{
		printf("\nDon't init this application");
	};		
	
	delete g_scene._imageDataSource;

	printf("\nClose program. \n");
	IupImageLibClose(); 
	IupClose();

	return 0;
}

